#include <OPP_Debug.h>
#include <string.h>
#include "DEV_HT7017.h"
#include "Opp_ErrorCode.h"
#include "OPP_Debug.h"
#include "OS.h"
#include "DRV_Usart.h"
#include <SVS_Para.h>


#pragma diag_suppress 1278

/*****************************************************************
Macro configs
*****************************************************************/
// Reg
#define REG_U           0x08 // 电压
#define REG_I1          0x06 // 通道1电流
#define REG_I2          0x07 // 通道2电流
#define REG_P1          0x0A // 通道1有功功率
#define REG_Q1          0x0B // 通道1无功功率
#define REG_S1          0x0C // 通道1视在功率
#define REG_E1          0x0D // 通道1电能
#define REG_ANAEN       0x43 // ADC开关寄存器
#define REG_ADCCONF     0x59 // 增益配置
#define REG_HFCONST     0x61 // 输出脉冲频率设置
#define REG_QPHSCAL     0x58 // 无功相位补偿
#define REG_GPHS1       0x6D // 通道1的相位校正（PQ方式）
#define REG_GP1         0x50 // 通道1的有功功率校正
#define REG_GQ1         0x51 // 通道1的无功功率校正
#define REG_GS1         0x52 // 通道1的视在功率校正
#define REG_P1OFFSETH   0x65 // 通道1有功功率偏置校正参数高8位
#define REG_P1OFFSETL   0x76 // 通道1有功功率偏置校正参数低8位
#define REG_Q1OFFSETH   0x67 // 通道1无功功率偏置校正参数高8位
#define REG_Q1OFFSETL   0x78 // 通道1无功功率偏置校正参数高8位
#define REG_I1RMSOFFSET 0x69 // 通道1有效值补偿寄存器
#define REG_I2RMSOFFSET 0x6A // 通道2有效值补偿寄存器
#define REG_I1OFF       0x5C // 电流通道1的偏置校正
#define REG_I2OFF       0x5D // 电流通道2的偏置校正
#define REG_UOFF        0x5E // 电压通道的偏置校正
#define REG_MODULEEN    0x42 // 模式控制寄存器（加宽P1OFFSET范围）
#define REG_NULL        0xFF // 无效寄存器

/*****************************************************************
Macros
*****************************************************************/
#define UART_MSG_HEAD         0x6A
#define UART_MSG_ACK_SUCCESS  0x54
#define UART_MSG_ADDR_READ(addr)  ((addr)&0x7F)
#define UART_MSG_ADDR_WRITE(addr) ((addr)|0x80)
#define METER_FLUSH_DELAY 650
#define METER_FLUSH_DELAY_1_CYCLE 350

/*****************************************************************
Macro utilities
*****************************************************************/
#define METER_INIT_CHECK_WITH_RETURN(init) if((init)==0) {return OPP_UNINIT;}
#define METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(chl,err) if((err)!=0) {MUTEX_UNLOCK(sDevHt7017Rts[chl-1].g_MeterAdjustProtectMutex);return err;}

/**
说明：如果硬件改了，则HFCONST需要重新核对，同时VALUE_KP的值也会跟着HFCONST的值改变而改变，需要重新计算；那么：
步骤一：硬件给出相关参数
HFConst = INT[K1*Vu*Vi*10^10/(EC*Un*Ib)]
K1=7.12
EC=3200
Vu= 0.0529*2(Gain)=0.1058 (V)
Vi= 0.003665*16(Gain)= 0.29312(A)
Un= 220 (V)
Ib= 5 (A)
HFConst = 627

步骤二：计算Kp
Kp=K2*10^10 / (HFConst*EC*2^23)
K2=5.625
EC=3200
HFCONST = $HFCONST
Kp = 0.003342

*/

// 寄存器-通道1
#define CH1_METER_EC 3200
#define CH1_VALUE_QPHSCAL     0xFF16
#define CH1_VALUE_ADCCONF     0x002D
//#define CH1_VALUE_HFCONST     7184     //((U32)((double)7.12*0.16*0.444*10000000000/(METER_EC*220*2)))
#define CH1_VALUE_HFCONST     627         ///< 0x14 HFConst(20 =7.12*0.0529*0.01832* 10^10/(3200*220*5))
#define CH1_VALUE_K_GAIN      100000000
#define CH1_VALUE_KU          21825036//5186206  // (1/VALUE_K_GAIN)
#define CH1_VALUE_KI1         190755//43881    // (1/VALUE_K_GAIN)
#define CH1_VALUE_KI2         0
#define CH1_VALUE_KP          334200    // (1/VALUE_K_GAIN)
#define CH1_VALUE_GPHS1       168//65400//65383
#define CH1_VALUE_GP1         1471//49883//49877
#define CH1_VALUE_P1OFFSETH   7
#define CH1_VALUE_P1OFFSETL   139
#define CH1_VALUE_I1RMSOFFSET 344
#define CH1_VALUE_I2RMSOFFSET 0
#define CH1_VALUE_GQ1         1471//49883//0
#define CH1_VALUE_MODULEEN    0x207E
#define CH1_VALUE_ANAEN       0x07
// 寄存器-通道2
#define CH2_METER_EC 3200
#define CH2_VALUE_QPHSCAL     0xFF16
#define CH2_VALUE_ADCCONF     0x002D
//#define CH2_VALUE_HFCONST     7184     //((U32)((double)7.12*0.16*0.444*10000000000/(METER_EC*220*2)))
#define CH2_VALUE_HFCONST     627         ///< 0x14 HFConst(20 =7.12*0.0529*0.01832* 10^10/(3200*220*5))
#define CH2_VALUE_K_GAIN      100000000
#define CH2_VALUE_KU          21825036//5186206  // (1/VALUE_K_GAIN)
#define CH2_VALUE_KI1         190755//43881    // (1/VALUE_K_GAIN)
#define CH2_VALUE_KI2         0
#define CH2_VALUE_KP          334200    // (1/VALUE_K_GAIN)
#define CH2_VALUE_GPHS1       168//65400//65383
#define CH2_VALUE_GP1         1471//49883//49877
#define CH2_VALUE_P1OFFSETH   7
#define CH2_VALUE_P1OFFSETL   139
#define CH2_VALUE_I1RMSOFFSET 344
#define CH2_VALUE_I2RMSOFFSET 0
#define CH2_VALUE_GQ1         1471//49883//0
#define CH2_VALUE_MODULEEN    0x207E
#define CH2_VALUE_ANAEN       0x03

typedef U32 reg_t;
typedef struct
{
    reg_t EC[DEV_METER_CHL_CNT];
    reg_t QPHSCAL[DEV_METER_CHL_CNT];
    reg_t ADCCONF[DEV_METER_CHL_CNT];
    reg_t HFCONST[DEV_METER_CHL_CNT];
    reg_t KGAIN[DEV_METER_CHL_CNT];
    reg_t KU[DEV_METER_CHL_CNT];
    reg_t KI1[DEV_METER_CHL_CNT];
    reg_t KI2[DEV_METER_CHL_CNT];
    reg_t KP[DEV_METER_CHL_CNT];
    reg_t GPHS1[DEV_METER_CHL_CNT];
    reg_t GP1[DEV_METER_CHL_CNT];
    reg_t P1OFFSETH[DEV_METER_CHL_CNT];
    reg_t P1OFFSETL[DEV_METER_CHL_CNT];
    reg_t I1RMSOFFSET[DEV_METER_CHL_CNT];
    reg_t I2RMSOFFSET[DEV_METER_CHL_CNT];
    reg_t GQ1[DEV_METER_CHL_CNT];
    reg_t MODULEEN[DEV_METER_CHL_CNT];
    reg_t ANAEN[DEV_METER_CHL_CNT];

}SRegValue;

const SRegValue sRv= {
    .EC          = {CH1_METER_EC,         CH2_METER_EC},
    .QPHSCAL     = {CH1_VALUE_QPHSCAL,    CH2_VALUE_QPHSCAL},
    .ADCCONF     = {CH1_VALUE_ADCCONF,    CH2_VALUE_ADCCONF},
    .HFCONST     = {CH1_VALUE_HFCONST,    CH2_VALUE_HFCONST},
    .KGAIN       = {CH1_VALUE_K_GAIN,     CH2_VALUE_K_GAIN},
    .KU          = {CH1_VALUE_KU,         CH2_VALUE_KU},
    .KI1         = {CH1_VALUE_KI1,        CH2_VALUE_KI1},
    .KI2         = {CH1_VALUE_KI2,        CH2_VALUE_KI2},
    .KP          = {CH1_VALUE_KP,         CH2_VALUE_KP},
    .GPHS1       = {CH1_VALUE_GPHS1,      CH2_VALUE_GPHS1},
    .GP1         = {CH1_VALUE_GP1,        CH2_VALUE_GP1},
    .P1OFFSETH   = {CH1_VALUE_P1OFFSETH,  CH2_VALUE_P1OFFSETH},
    .P1OFFSETL   = {CH1_VALUE_P1OFFSETL,  CH2_VALUE_P1OFFSETL},
    .I1RMSOFFSET = {CH1_VALUE_I1RMSOFFSET,CH2_VALUE_I1RMSOFFSET},
    .I2RMSOFFSET = {CH1_VALUE_I2RMSOFFSET,CH2_VALUE_I2RMSOFFSET},
    .GQ1         = {CH1_VALUE_GQ1,        CH2_VALUE_GQ1},
    .MODULEEN    = {CH1_VALUE_MODULEEN,   CH2_VALUE_MODULEEN},
    .ANAEN       = {CH1_VALUE_ANAEN   ,   CH2_VALUE_ANAEN},
};


// 参数-通道1
#define CH1_MPNUM_HFCONST    0x00 /* 校准参数对应的参数模块ID */
#define CH1_MPNUM_KU         0x01
#define CH1_MPNUM_KI1        0x02
#define CH1_MPNUM_KP         0x03
#define CH1_MPNUM_GPHS1      0x04
#define CH1_MPNUM_GP1        0x05
#define CH1_MPNUM_P1OFFSETH  0x06
#define CH1_MPNUM_P1OFFSETL  0x07
#define CH1_MPNUM_I1OFFSET   0x08
#define CH1_MPNUM_GQ1        0x09
#define CH1_MPNUM_MODULEEN   0x0A
#define CH1_MPNUM_KI2        0x0B
#define CH1_MPNUM_I2OFFSET   0x0C

// 参数-通道2
#define CH2_MPNUM_HFCONST    0x80 /* 校准参数对应的参数模块ID */
#define CH2_MPNUM_KU         0x81
#define CH2_MPNUM_KI1        0x82
#define CH2_MPNUM_KP         0x83
#define CH2_MPNUM_GPHS1      0x84
#define CH2_MPNUM_GP1        0x85
#define CH2_MPNUM_P1OFFSETH  0x86
#define CH2_MPNUM_P1OFFSETL  0x87
#define CH2_MPNUM_I1OFFSET   0x88
#define CH2_MPNUM_GQ1        0x89
#define CH2_MPNUM_MODULEEN   0x8A
#define CH2_MPNUM_KI2        0x8B
#define CH2_MPNUM_I2OFFSET   0x8C


/*****************************************************************
Variables
*****************************************************************/
typedef struct
{
    int init;                     /* 计量初始化状态 */
    T_MUTEX g_MeterInitMutex;           /* 计量初始化状态读写保护锁 */
    T_MUTEX g_MeterParaMutex;           /* 校准参数读写保护锁 */
    T_MUTEX g_MeterAdjustProtectMutex;  /* 校准过程保护锁 */
    T_MUTEX g_MeterStsMutex;            /* 统计过程保护锁 */
}SDevHt7017Rts;

static T_MUTEX g_MeterMutex;    /* 计量模块寄存器读写通信收发过程保护锁 */
static SDevHt7017Rts sDevHt7017Rts[DEV_METER_CHL_CNT] = {0};

static struct
{
    U32 u32Hfconst;     // 1/1
    U32 u32Ku;          // 1/VALUE_K_GAIN
    U32 u32Ki1;         // 1/VALUE_K_GAIN
    U32 u32Ki2;
    U32 u32Kp;          // 1/VALUE_K_GAIN
    U32 u32Gphs1;       // 1/1
    U32 u32Gp1;         // 1/1
    U32 u32P1offseth;   // 1/1
    U32 u32P1offsetl;   // 1/1
    U32 u32I1rmsoffset; // 1/1
    U32 u32I2rmsoffset; // 1/1
    U32 u32Gq1;         // 1/1
    U32 u32ModuleEn;    //

}sAdjPara[DEV_METER_CHL_CNT];

typedef struct{
    METER_ADJUST_PARA_EN enPara;
    U32 u32Reg;
    U32 u32Pnum;
    U32 *pu32Pram;
    U32 u32default;
    U32 u32WEN;
}SMeterRscItem;
const SMeterRscItem sMeterRscTable[DEV_METER_CHL_CNT][MAP_ID_MAX]={
{
    {.enPara=MAP_HFCONST,.u32Reg=REG_HFCONST,.u32Pnum=CH1_MPNUM_HFCONST,.pu32Pram=&sAdjPara[0].u32Hfconst,.u32default=CH1_VALUE_HFCONST,.u32WEN=0},
    {.enPara=MAP_KU,.u32Reg=REG_NULL,.u32Pnum=CH1_MPNUM_KU,.pu32Pram=&sAdjPara[0].u32Ku,.u32default=CH1_VALUE_KU,.u32WEN=1},
    {.enPara=MAP_KI1,.u32Reg=REG_NULL,.u32Pnum=CH1_MPNUM_KI1,.pu32Pram=&sAdjPara[0].u32Ki1,.u32default=CH1_VALUE_KI1,.u32WEN=1},
    {.enPara=MAP_KP,.u32Reg=REG_NULL,.u32Pnum=CH1_MPNUM_KP,.pu32Pram=&sAdjPara[0].u32Kp,.u32default=CH1_VALUE_KP,.u32WEN=0},
    {.enPara=MAP_GPHS1,.u32Reg=REG_GPHS1,.u32Pnum=CH1_MPNUM_GPHS1,.pu32Pram=&sAdjPara[0].u32Gphs1,.u32default=CH1_VALUE_GPHS1,.u32WEN=1},
    {.enPara=MAP_GP1,.u32Reg=REG_GP1,.u32Pnum=CH1_MPNUM_GP1,.pu32Pram=&sAdjPara[0].u32Gp1,.u32default=CH1_VALUE_GP1,.u32WEN=1},
    {.enPara=MAP_P1OFFSETH,.u32Reg=REG_NULL/*REG_P1OFFSETH WT*/,.u32Pnum=CH1_MPNUM_P1OFFSETH,.pu32Pram=&sAdjPara[0].u32P1offseth,.u32default=CH1_VALUE_P1OFFSETH,.u32WEN=1},
    {.enPara=MAP_P1OFFSETL,.u32Reg=REG_NULL/*REG_P1OFFSETL WT*/,.u32Pnum=CH1_MPNUM_P1OFFSETL,.pu32Pram=&sAdjPara[0].u32P1offsetl,.u32default=CH1_VALUE_P1OFFSETL,.u32WEN=1},
    {.enPara=MAP_I1OFFSET,.u32Reg=REG_NULL/*REG_I1RMSOFFSET WT*/,.u32Pnum=CH1_MPNUM_I1OFFSET,.pu32Pram=&sAdjPara[0].u32I1rmsoffset,.u32default=CH1_VALUE_I1RMSOFFSET,.u32WEN=1},
    {.enPara=MAP_GQ1,.u32Reg=REG_GQ1,.u32Pnum=CH1_MPNUM_GQ1,.pu32Pram=&sAdjPara[0].u32Gq1,.u32default=CH1_VALUE_GQ1,.u32WEN=1},
    {.enPara=MAP_MODULEEN,.u32Reg=REG_MODULEEN,.u32Pnum=CH1_MPNUM_MODULEEN,.pu32Pram=&sAdjPara[0].u32ModuleEn,.u32default=CH1_VALUE_MODULEEN,.u32WEN=0},
    {.enPara=MAP_KI2,.u32Reg=REG_NULL,.u32Pnum=CH1_MPNUM_KI2,.pu32Pram=&sAdjPara[0].u32Ki2,.u32default=CH1_VALUE_KI2,.u32WEN=1},
    {.enPara=MAP_I2OFFSET,.u32Reg=REG_I2RMSOFFSET,.u32Pnum=CH1_MPNUM_I2OFFSET,.pu32Pram=&sAdjPara[0].u32I2rmsoffset,.u32default=CH1_VALUE_I2RMSOFFSET,.u32WEN=1},
    },
{
    {.enPara=MAP_HFCONST,.u32Reg=REG_HFCONST,.u32Pnum=CH2_MPNUM_HFCONST,.pu32Pram=&sAdjPara[1].u32Hfconst,.u32default=CH2_VALUE_HFCONST,.u32WEN=0},
    {.enPara=MAP_KU,.u32Reg=REG_NULL,.u32Pnum=CH2_MPNUM_KU,.pu32Pram=&sAdjPara[1].u32Ku,.u32default=CH2_VALUE_KU,.u32WEN=1},
    {.enPara=MAP_KI1,.u32Reg=REG_NULL,.u32Pnum=CH2_MPNUM_KI1,.pu32Pram=&sAdjPara[1].u32Ki1,.u32default=CH2_VALUE_KI1,.u32WEN=1},
    {.enPara=MAP_KP,.u32Reg=REG_NULL,.u32Pnum=CH2_MPNUM_KP,.pu32Pram=&sAdjPara[1].u32Kp,.u32default=CH2_VALUE_KP,.u32WEN=0},
    {.enPara=MAP_GPHS1,.u32Reg=REG_GPHS1,.u32Pnum=CH2_MPNUM_GPHS1,.pu32Pram=&sAdjPara[1].u32Gphs1,.u32default=CH2_VALUE_GPHS1,.u32WEN=1},
    {.enPara=MAP_GP1,.u32Reg=REG_GP1,.u32Pnum=CH2_MPNUM_GP1,.pu32Pram=&sAdjPara[1].u32Gp1,.u32default=CH2_VALUE_GP1,.u32WEN=1},
    {.enPara=MAP_P1OFFSETH,.u32Reg=REG_NULL/*REG_P1OFFSETH WT*/,.u32Pnum=CH2_MPNUM_P1OFFSETH,.pu32Pram=&sAdjPara[1].u32P1offseth,.u32default=CH2_VALUE_P1OFFSETH,.u32WEN=1},
    {.enPara=MAP_P1OFFSETL,.u32Reg=REG_NULL/*REG_P1OFFSETL WT*/,.u32Pnum=CH2_MPNUM_P1OFFSETL,.pu32Pram=&sAdjPara[1].u32P1offsetl,.u32default=CH2_VALUE_P1OFFSETL,.u32WEN=1},
    {.enPara=MAP_I1OFFSET,.u32Reg=REG_NULL/*REG_I1RMSOFFSET WT*/,.u32Pnum=CH2_MPNUM_I1OFFSET,.pu32Pram=&sAdjPara[1].u32I1rmsoffset,.u32default=CH2_VALUE_I1RMSOFFSET,.u32WEN=1},
    {.enPara=MAP_GQ1,.u32Reg=REG_GQ1,.u32Pnum=CH2_MPNUM_GQ1,.pu32Pram=&sAdjPara[1].u32Gq1,.u32default=CH2_VALUE_GQ1,.u32WEN=1},
    {.enPara=MAP_MODULEEN,.u32Reg=REG_MODULEEN,.u32Pnum=CH2_MPNUM_MODULEEN,.pu32Pram=&sAdjPara[1].u32ModuleEn,.u32default=CH2_VALUE_MODULEEN,.u32WEN=0},
    {.enPara=MAP_KI2,.u32Reg=REG_NULL,.u32Pnum=CH2_MPNUM_KI2,.pu32Pram=&sAdjPara[1].u32Ki2,.u32default=CH2_VALUE_KI2,.u32WEN=1},
    {.enPara=MAP_I2OFFSET,.u32Reg=REG_I2RMSOFFSET,.u32Pnum=CH2_MPNUM_I2OFFSET,.pu32Pram=&sAdjPara[1].u32I2rmsoffset,.u32default=CH2_VALUE_I2RMSOFFSET,.u32WEN=1},
    },
};

U8 m_ucMeterInit[DEV_METER_CHL_CNT] = {0};
#define ERC_STATE_IDLE      0
#define ERC_STATE_CHECK     1
#define ERC_STATE_PRE_READ  2
#define ERC_STATE_RESET     3
#define ERC_STATE_READ      4
#define ERC_STATE_WAIT      5

#define ERC_T0_CHECK 30*1000
#define ERC_T_DELAY  650

/*****************************************************************
设备统计信息
*****************************************************************/
//static SDevHt7017StatusSts sDevHt7017StatusSts={0};
//static SDevHt7017StatusSts sDevHt7017StatusStsCache={0};
//static int devHt7017StaStsInit = 0;

void MrcInitSuccSts(void)
{
    //MUTEX_LOCK(g_MeterStsMutex, MUTEX_WAIT_ALWAYS);
    //sDevHt7017StatusSts.u32InitSuccCnt++;
    //MUTEX_UNLOCK(g_MeterStsMutex);
}
void MrcInitTotalSts(void)
{
    //MUTEX_LOCK(g_MeterStsMutex, MUTEX_WAIT_ALWAYS);
    //sDevHt7017StatusSts.u32InitTotalCnt++;
    //MUTEX_UNLOCK(g_MeterStsMutex);
}
void MrcSuccSts(void)
{
    //MUTEX_LOCK(g_MeterStsMutex, MUTEX_WAIT_ALWAYS);
    //sDevHt7017StatusSts.u32MrcSuccCnt++;
    //MUTEX_UNLOCK(g_MeterStsMutex);
}
void MrcReadSts(U32 u32Err)
{/*
    MUTEX_LOCK(g_MeterStsMutex, MUTEX_WAIT_ALWAYS);
    if(u32Err != 0) sDevHt7017StatusSts.u32MrcRFailCnt++;
    if(u32Err == 11) sDevHt7017StatusSts.u32MrcE11Cnt++;
    else if(u32Err == 12) sDevHt7017StatusSts.u32MrcE12Cnt++;
    else if(u32Err == 13) sDevHt7017StatusSts.u32MrcE13Cnt++;
    else if(u32Err == 14) sDevHt7017StatusSts.u32MrcE14Cnt++;
    else if(u32Err == 15) sDevHt7017StatusSts.u32MrcE15Cnt++;
    else{}
    MUTEX_UNLOCK(g_MeterStsMutex);*/
}
void MrcWriteSts(U32 u32Err)
{/*
    MUTEX_LOCK(g_MeterStsMutex, MUTEX_WAIT_ALWAYS);
    if(u32Err != 0) sDevHt7017StatusSts.u32MrcWFailCnt++;
    if(u32Err == 16) sDevHt7017StatusSts.u32MrcE16Cnt++;
    else if(u32Err == 17) sDevHt7017StatusSts.u32MrcE17Cnt++;
    else if(u32Err == 18) sDevHt7017StatusSts.u32MrcE18Cnt++;
    else{}
    MUTEX_UNLOCK(g_MeterStsMutex);*/
}

int MeterInitGet(U8 u8Chl);
/**
@brief 计量设备统计信息获取接口
@param pst 消息接收结构体
@param pu32ChgFlag 和上次读取的值是否变化,0:没变化，1：变化了
@retval 0:成功
*/
U32 MeterDevStatusStsGet(SDevHt7017StatusSts *pst,U32 *pu32ChgFlag)
{/*
    sDevHt7017StatusSts.u32InitCur = MeterInitGet();

    MUTEX_LOCK(g_MeterStsMutex, MUTEX_WAIT_ALWAYS);
    memcpy(pst,&sDevHt7017StatusSts,sizeof(SDevHt7017StatusSts));
    MUTEX_UNLOCK(g_MeterStsMutex);

    if(memcmp(&sDevHt7017StatusStsCache,pst,sizeof(SDevHt7017StatusSts))!=0)
    {
        if(devHt7017StaStsInit == 0)
        {
            devHt7017StaStsInit = 1;
            if(pst->u32InitCur==1
            && pst->u32InitSuccCnt==1
            && pst->u32InitTotalCnt==1)
            {
                *pu32ChgFlag = 0;
            }
            else
            {
                *pu32ChgFlag = 1;
            }
        }
        else
        {
            *pu32ChgFlag = 1;
        }
    }
    else
    {
        *pu32ChgFlag = 0;
    }

    memcpy(&sDevHt7017StatusStsCache,pst,sizeof(SDevHt7017StatusSts));*/
    return 1;
}

/*****************************************************************
Utilities
*****************************************************************/
#define DEV_POWER_RELAY_ON   13000 // 继电器开的控制板功率，单位0.1mW
#define DEV_POWER_RELAY_OFF  18000 // 继电器关的控制板功率，单位0.1mW

/**
@breif 获取控制器自身能耗
@note 根据开关灯时间和控制器功率计算得到
@param u8Chl 通道号（1-2）
@retval 能耗,单位1/3200KWH (从1/12000 KWH改为)
*/
static U32 DevEnergyGet(u8 u8Chl)
{
    return 0;
    #if 0
    U32 u32OnTime,u32RunTime,u32OffTime;
    U32 u32Energy;

    OppLampCtrlGetLtime(0,&u32OnTime);    // 获取亮灯时间，单位Min
    OppLampCtrlGetRtime(0,&u32RunTime);   // 获取运行时间，单位Min
    u32OffTime = (u32RunTime>=u32OnTime)?(u32RunTime-u32OnTime):0; // 计算关灯时间,单位Min

    u32Energy = (u32OnTime*DEV_POWER_RELAY_ON + u32OffTime*DEV_POWER_RELAY_OFF)*32/6000000; // 计算控制器能耗
    return u32Energy;
    #endif
}

const SMeterRscItem* findItemInMeterRscTable(U8 u8Chl,METER_ADJUST_PARA_EN enPara)
{
    const SMeterRscItem* psItem = 0;

    if(u8Chl == 0 || u8Chl > DEV_METER_CHL_CNT){
        return 0;
    }

    for(int i=0;i<MAP_ID_MAX;i++)
    {
        if(sMeterRscTable[u8Chl-1][i].enPara == enPara)
        {
            psItem = &sMeterRscTable[u8Chl-1][i];
            break;
        }
    }
    return psItem;
}

uint8_t MeterUartInit()
{
#if 0
    esp_err_t err;

    uart_config_t uart_config = {
        .baud_rate = 4800,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_EVEN,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_config.baud_rate = brate;
    uart_config.data_bits = dbits;
    uart_config.parity = cparity;
    /*CLI_PRINTF("Uart init brate:%d,dbits:%d,cparity:%d,stop_bits:%d,flow_ctrl:%d\r\n",\
    uart_config.baud_rate,uart_config.data_bits,uart_config.parity,uart_config.stop_bits,uart_config.flow_ctrl);*/

    err = uart_driver_delete(uart_num);
    if (err != ESP_OK) {
        return 1;
    }

    err = uart_param_config(uart_num, &uart_config);
    if (err != ESP_OK) {
        return 2;
    }

    err = uart_set_pin(uart_num, tx_io_num, rx_io_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    if (err != ESP_OK) {
        return 3;
    }

    err = uart_driver_install(uart_num,  256/*rx_buffer_size*/, 0/*tx_buffer_size*/, 0, NULL, 0);
    if (err != ESP_OK) {
        return 4;
    }
#else
    //wangtao
    usart_config_init(&usart3_context,4800,USART_WordLength_9b,USART_Parity_Even);
#endif
    return 0;
}

/**
@brief 计量模块串口读取
@param u8Chl 通道号1-2
@param pu8Buf 数据
@param u32Len 长度
@param u32TicksToWait 等待tick值
@retval 返回读取长度
*/
int MeterUartReadBytes(U8 u8Chl,U8* pu8Buf,U32 u32Len,U32 u32TicksToWait)
{
    /*if(u8Chl == 1){
        BspGpioSPDTSet(0);
    }else if(u8Chl == 2){
        BspGpioSPDTSet(1);
    }else{
        return 0;
    }

    OS_DELAY_MS(2);*/
    return uart_read_bytes(&usart3_context,pu8Buf,u32Len,u32TicksToWait);
}

/**
@brief 计量模块串口写入
@param u8Chl 通道号1-2
@param pu8Buf 数据
@param u32Len 长度
@retval 返回写入长度
*/
int MeterUartWriteBytes(U8 u8Chl,U8* pu8Buf,U32 u32Len)
{
    //switch channel,note by wangtao
    /*if(u8Chl == 1){
        BspGpioSPDTSet(0);
    }else if(u8Chl == 2){
        BspGpioSPDTSet(1);
    }else{
        return 0;
    }

    OS_DELAY_MS(2);*/

    return uart_write_bytes(&usart3_context,(const char*)pu8Buf,u32Len);
}

int MeterUartRegRead()
{
    return 0;
}

int MeterUartRegWrite()
{
    return 0;
}

/*****************************************************************
Meter utilities
*****************************************************************/
int MeterInitGet(U8 u8Chl)
{
    int init;
    METER_CHL_CHECK_WITH_RETURN(u8Chl,0);
    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterInitMutex, MUTEX_WAIT_ALWAYS);
    init = sDevHt7017Rts[u8Chl-1].init;
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterInitMutex);
    return init;
}
void MeterInitSet(U8 u8Chl,int init)
{
    if(u8Chl < 1 || u8Chl > DEV_METER_CHL_CNT) return;
    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterInitMutex, MUTEX_WAIT_ALWAYS);
    sDevHt7017Rts[u8Chl-1].init = init;
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterInitMutex);
}

/*基础寄存器操作*/
/*读三个字节*/
uint8_t MeterRegRead(U8 u8Chl,unsigned char addr,unsigned char *out ,unsigned char outLenMax)
{
    int uart_res;
    unsigned char tx_buf[2],rx_buf[10];
    unsigned char check;

    //u_tm_log("111here\r\n");
    METER_CHL_CHECK_WITH_RETURN(u8Chl,1);
    //METER_INIT_CHECK_WITH_RETURN(sMeterInit);
    //u_tm_log("222here\r\n");
    if(outLenMax < 3) return OPP_FAILURE;
    //u_tm_log("333here\r\n");

    MUTEX_LOCK(g_MeterMutex, MUTEX_WAIT_ALWAYS);
    /*
     TX:HEAD CMD
     RX:         D2 D1 D0 CHECKSUM
    */
    /*清串口缓冲*/
    /*err = uart_flush_input(GPS_UART_NUM);
    if(err != 0)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 11;
    }
    err = uart_flush(GPS_UART_NUM);
    if(err != 0)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 12;
    }*/

    /*发送*/
    tx_buf[0]=UART_MSG_HEAD;
    tx_buf[1]=UART_MSG_ADDR_READ(addr); // Read
    uart_res = MeterUartWriteBytes(u8Chl,(unsigned char*)tx_buf,2);
    //u_tm_log("send uart_res=%d\r\n",uart_res);
    if(uart_res!=2)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 13;
    }

    /*接收*/
    uart_res = MeterUartReadBytes(u8Chl,rx_buf,4,500);
    if(uart_res != 4)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 14;
    }
    /*Check*/
    check = tx_buf[0]+tx_buf[1]+rx_buf[0]+rx_buf[1]+rx_buf[2];
    if((U8)(~check)!=rx_buf[3])
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 15;
    }
    out[0] = rx_buf[0];
    out[1] = rx_buf[1];
    out[2] = rx_buf[2];

    MUTEX_UNLOCK(g_MeterMutex);
    return 0;
}

/*写两个字节*/
uint8_t MeterRegWrite(U8 u8Chl,unsigned char addr,unsigned char *in,unsigned char inLen)
{
    int uart_res;
    unsigned char tx_buf[6],rx_buf[10];
    unsigned char check;

    //METER_INIT_CHECK_WITH_RETURN(sMeterInit);
    if(inLen == 0 || inLen > 2) return OPP_FAILURE;

    MUTEX_LOCK(g_MeterMutex, MUTEX_WAIT_ALWAYS);
    /*
     TX:HEAD CMD D1 D0 CHECKSUM
     RX:                        ACK
    */
    //wangtao
    /*清串口缓冲*/
    /*err = uart_flush_input(GPS_UART_NUM);
    if(err != 0)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 11;
    }
    err = uart_flush(GPS_UART_NUM);
    if(err != 0)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 12;
    }*/
    /*发送*/
    tx_buf[0]=UART_MSG_HEAD;
    tx_buf[1]=UART_MSG_ADDR_WRITE(addr); // Write
    if(inLen == 1)
    {
        tx_buf[2]=0;
        tx_buf[3]=in[0];
    }
    else
    {
        tx_buf[2]=in[0];
        tx_buf[3]=in[1];
    }
    check = (tx_buf[0]+tx_buf[1]+tx_buf[2]+tx_buf[3]);
    tx_buf[4]=~check;
    uart_res = MeterUartWriteBytes(u8Chl,(unsigned char*)tx_buf,5);
    if(uart_res!=5)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 13;
    }
    //OS_DELAY_MS(20);
    /*接收*/
    uart_res = MeterUartReadBytes(u8Chl,rx_buf,1,500);
    if(uart_res != 1)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 14;
    }

    /*Ack*/
    check = rx_buf[0];
    if(check!=UART_MSG_ACK_SUCCESS)
    {
        MUTEX_UNLOCK(g_MeterMutex);
        return 15;
    }
    MUTEX_UNLOCK(g_MeterMutex);

    return 0;
}

uint8_t MeterParaRead(U8 u8Chl,U32 addr,U32* value)
{
    unsigned char buf[3]={0};
    uint8_t err;

    METER_CHL_CHECK_WITH_RETURN(u8Chl,1);

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterParaMutex,MUTEX_WAIT_ALWAYS);
    err = MeterRegRead(u8Chl,addr,buf,3);
    *value = 0;
    *value += buf[0];
    *value <<= 8;
    *value += buf[1];
    *value <<= 8;
    *value += buf[2];
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterParaMutex);

    return err;
}
uint8_t MeterParaWrite(U8 u8Chl,U32 addr,U16 value)
{
    unsigned char buf[2]={0};
    uint8_t err;
    U16 wpcfg;

    METER_CHL_CHECK_WITH_RETURN(u8Chl,1);
    /* WPCFG(32H):
       0xA6:0x50 - 0x7c
       0xBC:0x40 - 0x45
       else:disable
    */
    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterParaMutex,MUTEX_WAIT_ALWAYS);
    // Enable wpcfg
    if(addr >= 0x50 && addr <= 0x7c) wpcfg = 0xA6;
    else if(addr >= 0x40 && addr <= 0x45) wpcfg = 0xBC;
    else wpcfg = 0;

    buf[0] = (U8)(wpcfg>>8);
    buf[1] = (U8)(wpcfg&0x00FF);
    err = MeterRegWrite(u8Chl,0x32,buf,2);

    // Write
    if(err == 0){
        buf[0] = (U8)(value>>8);
        buf[1] = (U8)(value&0x00FF);
        err = MeterRegWrite(u8Chl,addr,buf,2);
    }

    // Disable wpcfg
    wpcfg = 0;
    buf[0] = (U8)(wpcfg>>8);
    buf[1] = (U8)(wpcfg&0x00FF);
    err = MeterRegWrite(u8Chl,0x32,buf,2);

    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterParaMutex);

    if(err != 0) return 16;

    /* 回读确认 */
    U32 out;
    err = MeterParaRead(u8Chl,addr,&out);
    if(err != 0)
    {
        return 17;
    }
    // 读出三个字节，使用后两个字节和写入的两个字节对比
    if(value != out)
    {
        return 18;
    }

    return err;
}

/*复位及初始化*/
/*软复位 0x33->0x55*/
uint8_t MeterReset(U8 u8Chl)
{
    // 不能调用MeterParaWrite()接口，因为0x33寄存器写入0x55后读出来还是0，通不过回读确认
    U8 value = 0x55;
    return MeterRegWrite(u8Chl,0x33,&value,1);
}
/*硬复位，注意，硬复位会把两路计量都复位了 */
uint8_t MeterHwResetTest(void)
{
    uint8_t err;
    uint8_t ret=0;
    //unsigned char buf[5];
    U32 para=0;

    //wangtao, meter hardware reset
    /*err = BspGpioMeterResetSet(0);
    OS_DELAY_MS(20);
    if(err != 0){
        ret =  1;
    }else{
        ret = 0;
    }

    err = BspGpioMeterResetSet(1);
    OS_DELAY_MS(20);*/
    if(err != 0){
        ret =  2;
    }else{
        err = MeterParaRead(1,0x59,&para);
        if(err != 0){
            ret = 4;
        }else{
            if(para == 0){
                ret = 0;
            }else{
                ret = 5;
            }
        }

        err = MeterParaRead(2,0x59,&para);
        if(err != 0){
            ret = 14;
        }else{
            if(para == 0){
                ret = 0;
            }else{
                ret = 15;
            }
        }
    }
    MeterInitSet(1,0); ///< 复位管脚将复位两个计量模块
    MeterInitSet(2,0); ///< 复位管脚将复位两个计量模块

    return ret;
}

inline static uint8_t MeterLoadAdjParaToReg(U8 u8Chl)
{
    uint8_t err;
    const SMeterRscItem* psItem;

    for(int i=0;i<MAP_ID_MAX;i++)
    {
        psItem = findItemInMeterRscTable(u8Chl,(METER_ADJUST_PARA_EN)i);
        if(psItem == 0) return 1;

        if(psItem->u32Reg != REG_NULL){
            err = MeterParaWrite(u8Chl,psItem->u32Reg,*(psItem->pu32Pram));
            if(err != 0) return err;
        }
    }
    return 0;
}

uint8_t MeterStart(void)
{
    uint8_t err;
    U8 u8Chl;

    MrcInitTotalSts(); // 统计初始化总次数

    /*硬件复位*/
    //note by wangtao
    /*BspGpioMeterResetSet(0);
    OS_DELAY_MS(20);
    BspGpioMeterResetSet(1);
    OS_DELAY_MS(20);*/

    //wangtao
    for(int i = 0; i < DEV_METER_CHL_CNT;i++){
        u8Chl = i + 1;

        /*软复位*/
        err = MeterReset(u8Chl);
        if(err != 0) return 11;

        /*寄存器启动流程及配置*/
        // 配置ADCON
        err = MeterParaWrite(u8Chl,REG_ADCCONF,sRv.ADCCONF[u8Chl-1]);
        if(err != 0) return 12;
        // 配置QPHSCAL
        err = MeterParaWrite(u8Chl,REG_QPHSCAL,sRv.QPHSCAL[u8Chl-1]);
        if(err != 0) return 13;
        // 配置ANAEN,开启第二路电流
        if(u8Chl == 1){
            err = MeterParaWrite(u8Chl,REG_ANAEN,sRv.ANAEN[u8Chl-1]);
            if(err != 0) return 15;
        }

        /*加载校准参数*/
        err = MeterLoadAdjParaToReg(u8Chl);
        if(err != 0) return 14;
    }

    /* 延时 */
    OS_DELAY_MS(METER_FLUSH_DELAY);

    MrcInitSuccSts();//统计初始化成功次数

    return 0;
}

/*重新初始化*/
uint8_t MeterReinit(void)
{
    uint8_t err;

    //METER_CHL_CHECK_WITH_RETURN(u8Chl,1);

    MUTEX_LOCK(sDevHt7017Rts[1-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);//保护校准过程
    MUTEX_LOCK(sDevHt7017Rts[2-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);

    MeterInitSet(1,0);
    MeterInitSet(2,0);

    err = MeterStart();
    if(err == 0){
        MeterInitSet(1,1);
        MeterInitSet(2,1);
    }

    MUTEX_UNLOCK(sDevHt7017Rts[1-1].g_MeterAdjustProtectMutex);
    MUTEX_UNLOCK(sDevHt7017Rts[2-1].g_MeterAdjustProtectMutex);

    return err;
}

uint8_t MeterDumpReg()
{
    return 1;
}

uint8_t MeterInitRepair(U8 u8Chl)
{
    uint8_t res;

    if(MeterInitGet(u8Chl) == 0){
        if(MeterStart() == 0){
            MeterInitSet(1,1);
            MeterInitSet(2,1);
            res = 0;
        }else{
            res = 1;
        }
    }else{
        res = 0;
    }
    return res;
}

/*
@brief 寄存器纠正
@param addr 地址
@param value 值
@return 0:本来就一致，1：矫正成功，2：读取失败，3:重新写入失败,4:初始化失败
*/
U32 MeterRegCorrect(U8 u8Chl,U32 addr,U32 value)
{
    U32 out;
    U32 err;

    err = MeterParaRead(u8Chl,addr,&out);
    MrcReadSts(err);// 统计寄存器校正读取的结果
    if(err != 0) {
        DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterParaRead err=%u\r\n",err);
        return 2;
    }

    if(value == out) return 0;

    err = MeterParaWrite(u8Chl,addr,value);
    MrcWriteSts(err);// 统计寄存器校正写入的结果
    if(err!=0) {
        DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterParaWrite err=%u\r\n",err);
        return 3;
    }

    MrcSuccSts(); // 统计寄存器校正成功次数（不包括本来就对的）
    return 1;
}

/*
    @brief 寄存器纠正
    @return 严重程度0-10
*/
U32 MeterRegRepairAll(U8 u8Chl)
{
    U32 err,ret=0;
    const SMeterRscItem* psItem;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    if(MeterInitGet(u8Chl)==0) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}

    /*
    寄存器         功能                              地址  值   说明
    GP1         通道1的有功功率校正                      0x50    默认校准参数
    GQ1         通道1的无功功率校正                      0x51    默认校准参数
    QPhsCal     无功相位补偿                          0x58    0xFF16
    ADCCON      ADC通道增益选择                       0x59    0x002D
    I1off       电流通道1的偏置校正                      0x5C    0
    Uoff        电压通道的偏置校正                       0x5E    0
    HFConst     输出脉冲频率设置                        0x61    5748
    P1OFFSETH   通道1有功功率偏置校正参数高8位                0x65    默认校准参数
    P1OFFSETL   通道1有功功率偏置校正参数低8位                0x76    默认校准参数
    I1RMSOFFSET 通道1有效值补偿寄存器                     0x69    默认校准参数
    GPhs1       通道1的相位校正（PQ方式）                  0x6D    默认校准参数
    */
    for(int i = 0;i < MAP_ID_MAX;i++)
    {
        psItem = findItemInMeterRscTable(u8Chl,(METER_ADJUST_PARA_EN)i);
        if(psItem == 0) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}

        if(psItem ->u32Reg != REG_NULL)
        {
            err = MeterRegCorrect(u8Chl,psItem ->u32Reg ,*(psItem->pu32Pram) );
            if(err != 0) DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterCheck[Block1] err occur,id:%d,res=%u\r\n",psItem->enPara,err);
            if(err == 2 || err == 3 || err ==4) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}
            else if(err == 1) ret += 1;
        }
    }

    err = MeterRegCorrect(u8Chl,REG_QPHSCAL ,sRv.QPHSCAL[u8Chl-1] );
    if(err != 0) DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterCheck[Block2,REG_QPHSCAL] err occur,res=%u\r\n",err);
    if(err == 2 || err == 3 || err ==4) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}
    else if(err == 1) ret += 1;

    err = MeterRegCorrect(u8Chl,REG_ADCCONF ,sRv.ADCCONF[u8Chl-1] );
    if(err != 0) DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterCheck[Block2,REG_ADCCONF] err occur,res=%u\r\n",err);
    if(err == 2 || err == 3 || err ==4) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}
    else if(err == 1) ret += 1;

    err = MeterRegCorrect(u8Chl,REG_I1OFF ,0 );
    if(err != 0) DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterCheck[Block2,REG_I1OFF] err occur,res=%u\r\n",err);
    if(err == 2 || err == 3 || err ==4) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}
    else if(err == 1) ret += 1;

    err = MeterRegCorrect(u8Chl,REG_UOFF ,0 );
    if(err != 0) DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_WARN, "MeterCheck[Block2,REG_UOFF] err occur,res=%u\r\n",err);
    if(err == 2 || err == 3 || err ==4) {MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);return 10;}
    else if(err == 1) ret += 1;

    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);
    return ret;
}

/*****************************************************************
Interfaces
*****************************************************************/
inline static uint8_t MeterLoadParaFraomFlashToRam(U8 u8Chl)
{
    U32 value,v;
    const SMeterRscItem* psItem;

    for(int i=0;i<MAP_ID_MAX;i++)
    {
        psItem = findItemInMeterRscTable(u8Chl,(METER_ADJUST_PARA_EN)i);
        if(psItem == 0) return 1;

        //wangtao
        if(AppParaReadU32(APS_PARA_MODULE_APS_METER,psItem->u32Pnum,&value)==0){
            v = value;
        }else{
            v = psItem->u32default;
        }

        if(v != *(psItem->pu32Pram))
        {
         *(psItem->pu32Pram) = v;
        }
    }
    return 0;
}

/*初始化*/
uint8_t MeterInit(void)
{
    uint8_t err = 0;
    U8 u8Chl;

    /*串口及GPIO初始化*/
    err+=MeterUartInit();
    //if(err != 0){
    //    return 1;
    //}
    MUTEX_CREATE(g_MeterMutex);
    for(int i = 0;i < DEV_METER_CHL_CNT;i++)
    {
        u8Chl = i + 1;

        /*变量初始化*/
        MUTEX_CREATE(sDevHt7017Rts[i].g_MeterInitMutex);
        MUTEX_CREATE(sDevHt7017Rts[i].g_MeterParaMutex);
        MUTEX_CREATE(sDevHt7017Rts[i].g_MeterAdjustProtectMutex);
        MUTEX_CREATE(sDevHt7017Rts[i].g_MeterStsMutex);

        //Not support flash para, wangtao
        /*参数加载从FLASH载入RAM*/
        err += MeterLoadParaFraomFlashToRam(u8Chl);
        if(err != 0){
            return 2;
        }

        MeterInitSet(u8Chl,1);
    }
    /*计量模块初始化*/
    err += MeterStart();
    //if(err != 0){
    //    return 3;
    //}
    return err;
}

/*计量数据获取*/
uint8_t MeterInstantInfoGet(U8 u8Chl,meter_info_t *info)
{
    uint8_t err;
    U32 value;

    if(info==0) return OPP_NULL_POINTER;
    //METER_INIT_CHECK_WITH_RETURN(MeterInitGet());
    if(MeterInitRepair(u8Chl) != 0)
    {
        return 10;
    }

    // 重新加载校准参数
    MeterLoadParaFraomFlashToRam(u8Chl);

    // 电压
    err = MeterParaRead(u8Chl,REG_U,&value);
    if(err!=0) return 11;
    info->u32Voltage = (U64)value*sAdjPara[u8Chl-1].u32Ku/sRv.KGAIN[u8Chl-1]; // mV
    info->u32Voltage /= 100; // mV->0.1V

    // 电流
    err = MeterParaRead(u8Chl,REG_I1,&value);
    if(err!=0) return 12;
    info->u32Current = (U64)value*sAdjPara[u8Chl-1].u32Ki1/sRv.KGAIN[u8Chl-1]; // mA
    //电流小于5mA赋值0
    if(info->u32Current<5)
    {
        info->u32Current=0;
    }
    // 漏电电流
#ifdef CONFIG_DRV_METER_LC
    if(u8Chl == 1){
        err = MeterParaRead(u8Chl,REG_I2,&value);
        if(err!=0) return 14;
        info->u32LkCurrent = (U64)value*sAdjPara[u8Chl-1].u32Ki2/sRv.KGAIN[u8Chl-1]; // mA
    }else{
        info->u32LkCurrent = 0;
    }
#else
    info->u32LkCurrent = -1;//-1漏电无效
#endif
    // 功率
    /*
       Preg = PowerP1        ; PowerP1<2^23
       Preg = PowerP1 - 2^24 ; PowerP1 >= 2^23
    */
    err = MeterParaRead(u8Chl,REG_P1,&value);
    if(err!=0) return 13;
    value = value>=0x800000?(((~value)&0xFFFFFF)+1):value;
    info->u32Power = (U64)value*sAdjPara[u8Chl-1].u32Kp*10000/sRv.KGAIN[u8Chl-1]; // 0.1mW
    //电流为0功率为0
    if(info->u32Current==0)
    {
        info->u32Power = 0;
    }

    // 功率因素
    value = (info->u32Voltage) * (info->u32Current);
    if(value == 0){
        info->u32PowerFactor = 0;
    }else{
        info->u32PowerFactor = (double)info->u32Power*1000/value;
        if(info->u32PowerFactor>1000) info->u32PowerFactor=1000;
    }
    //电流为0功率因数为0
    if(info->u32Current==0)
    {
        info->u32PowerFactor = 0;
    }
    // 漏电电流（兼容）
    //info->u32LkCurrent = 0;

    return 0;
}

uint8_t MeterInfoGet(U8 u8Chl,meter_info_t *info)/*历史遗留接口*/
{
    uint8_t err;
    U32 value;

    if(info==0) return OPP_NULL_POINTER;
    // 电压
    // 电流
    // 功率
    // 功率因素
    err = MeterInstantInfoGet(u8Chl,info);
    if(err!=0) return err;

    // 电能
    err = MeterParaRead(u8Chl,REG_E1,&value);
    if(err!=0) return 16;
    info->u16Energy = value + DevEnergyGet(u8Chl);

    return 0;
}

U32 ElecRegTo1pk(U32 reg)
{
    // EC = 3200
    U32 ret;
    ret = (U32)((double)reg/3.2);
    return ret;
}
U32 Elec1pkToReg(U32 reg)
{
    U32 ret;

    ret = (U32)((double)reg*3.2);

    return ret;
}

int NormalElecInfoGet(U8 u8Chl,NORMAL_ELECTRIC_INFO_ST *pstElecInfo)
{
    meter_info_t info;
    uint8_t err;

    err=MeterInfoGet(u8Chl,&info);
    if(err!=0) return err;

    pstElecInfo->consumption = ElecRegTo1pk(info.u16Energy);
    pstElecInfo->power = info.u32Power / 10000;
    pstElecInfo->voltage = info.u32Voltage/10;
    pstElecInfo->current = info.u32Current;
    pstElecInfo->factor=info.u32PowerFactor;
    //pstElecInfo->hisConsumption = ElecRegTo1pk(ElecHisConsumptionGetInner(u8Chl));
    return 0;
}

/*校准参数获取*/
int MeterAdjustParaRead(U8 u8Chl,METER_ADJUST_PARA_EN enPara,U32 *u32Value)
{
    const SMeterRscItem* psItem;

    psItem = findItemInMeterRscTable(u8Chl,enPara);
    if(psItem == 0) return 1;

    *u32Value = *(psItem->pu32Pram);

    return 0;
}

/*校准参数设置*/
int MeterAjustParaWrite(U8 u8Chl,METER_ADJUST_PARA_EN enPara,U32 u32Value)
{
    // 写入寄存器
    // 存入FLASH
    // 更新到RAM

    const SMeterRscItem* psItem;

    psItem = findItemInMeterRscTable(u8Chl,enPara);
    if(psItem == 0) return 1;

    if(psItem->u32WEN == 0) return 2;

    if(psItem->u32Reg != REG_NULL){
        if(MeterParaWrite(u8Chl,psItem->u32Reg, u32Value)!=0)
        {
            return 3;
        }
    }
    //not support calc para write to flash wangtao
    if(AppParaWriteU32(APS_PARA_MODULE_APS_METER,psItem->u32Pnum,u32Value)!=0)
    {
        return 4;
    }

    *(psItem->pu32Pram) = u32Value;

    return 0;
}

/*校准参数恢复默认值*/
int MeterAjustParaSetDefault(U8 u8Chl)
{
    int err=0;
    const SMeterRscItem* psItem;

    for(int i=0;i<MAP_ID_MAX;i++)
    {
        psItem = findItemInMeterRscTable(u8Chl,(METER_ADJUST_PARA_EN)i);
        if(psItem == 0) return 1;

        if(psItem->u32WEN != 0 ){
            if(MeterAjustParaWrite(u8Chl,(METER_ADJUST_PARA_EN)i,sMeterRscTable[u8Chl-1][i].u32default)!=0){
                err = 2;
            }
        }
    }
    return err;

}

inline static int MeterAdjSmp(U8 u8Chl,U32 u32SmpCnt,U32 u32SmpCntDefault, U32 u32Addr,U32* pu32Value,U32 u32Addr2,U32* pu32Value2)
{
    U32  err,reg;
    unsigned long long total1=0,total2=0;

    if(u32Addr == REG_NULL && u32Addr2 == REG_NULL) return 1;

    if(u32SmpCnt == 0) u32SmpCnt = u32SmpCntDefault;

    for(int i = 0;i < u32SmpCnt;i++)
    {
        if(u32Addr != REG_NULL){
            err = MeterParaRead(u8Chl,u32Addr,&reg);
            if(err != 0) return 2;
            total1 += reg;
        }
        if(u32Addr2 != REG_NULL){
            err = MeterParaRead(u8Chl,u32Addr2,&reg);
            if(err != 0) return 3;
            total2 += reg;
        }
        OS_DELAY_MS(METER_FLUSH_DELAY_1_CYCLE); ///< 延迟
    }
    if(u32Addr != REG_NULL) *pu32Value = (U32)(total1/u32SmpCnt);
    if(u32Addr2 != REG_NULL) *pu32Value2 = (U32)(total2/u32SmpCnt);

    return 0;
}

/*校准*/
// u32Value:mV
int KUAdjust(U8 u8Chl,U32 u32Value,U32 u32SmpCnt)
{
    U32 reg;
    int err;
    U32 k;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    //err = MeterParaRead(REG_U,&reg);
    err = MeterAdjSmp(u8Chl,u32SmpCnt,1,REG_U,&reg,REG_NULL,&reg);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    if(reg == 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);
    k = (U32)((float)u32Value* sRv.KGAIN[u8Chl-1] / reg);

    err = MeterAjustParaWrite(u8Chl,MAP_KU,k);
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);

    return err;
}

// u32Value:0.01mA
int KI1Adjust(U8 u8Chl,U32 u32Value,U32 u32SmpCnt)
{
    U32 reg;
    int err;
    U32 k;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    //err = MeterParaRead(REG_I1,&reg);
    err = MeterAdjSmp(u8Chl,u32SmpCnt,1,REG_I1,&reg,REG_NULL,&reg);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    if(reg == 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);
    k = (U32)((float)u32Value* sRv.KGAIN[u8Chl-1] / ((float)reg * 100));

    err = MeterAjustParaWrite(u8Chl,MAP_KI1,k);

    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);
    return err;
}

// u32Volt:mV
// u32Cur:0.01mA
int KUKI1Adjust(U8 u8Chl,U32 u32Volt,U32 u32Cur,U32 u32SmpCnt)
{
    U32 regVolt,regCur;
    int err;
    U32 k;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    err = MeterAdjSmp(u8Chl,u32SmpCnt,1,REG_U,&regVolt,REG_I1,&regCur);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    if(regVolt == 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);
    if(regCur == 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);

    k = (U32)((float)u32Volt* sRv.KGAIN[u8Chl-1] / regVolt);
    err = MeterAjustParaWrite(u8Chl,MAP_KU,k);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    printf("KU=%d\r\n",k);
    k = (U32)((float)u32Cur* sRv.KGAIN[u8Chl-1] / ((float)regCur * 100));
    err = MeterAjustParaWrite(u8Chl,MAP_KI1,k);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    printf("KI1=%d\r\n",k);

    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);
    return 0;
}

int AbsPreg(U32 value)
{
    return value>=0x800000?(((~value)&0xFFFFFF)+1):value;
}

// u32V1:mW,u32V2:mVar
int GP1GPHS1Adjust(U8 u8Chl,U32 u32V1,U32 u32V2,U32 u32SmpCnt)
{
    float Preal=u32V1,Qreal=u32V2,PowerP,PowerQ;
    float th,ftmp;
    U32 gphs1,value1,value2;
    int err;

    Preal = Preal/1000;
    Qreal = Qreal/1000;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    // 先清除相关校准参数对应的寄存器

    err = MeterParaWrite(u8Chl,REG_GP1,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    err = MeterParaWrite(u8Chl,REG_GQ1,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    err = MeterParaWrite(u8Chl,REG_GPHS1,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);


    OS_DELAY_MS(METER_FLUSH_DELAY); ///< 300改为350

    err = MeterAdjSmp(u8Chl,u32SmpCnt,1,REG_P1,&value1,REG_Q1,&value2);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    PowerP = AbsPreg(value1);
    PowerQ = AbsPreg(value2);

    //err = MeterParaRead(REG_P1,&value);
    //err = MeterParaRead(REG_Q1,&value);
    //printf("REG_P1:%d(0x%06x)\r\n",value1,value1);
    //printf("AbsPreg(REG_P1):%d(0x%06x),PowerP:%f\r\n",(U32)PowerP,(U32)PowerP,PowerP);
    //printf("REG_Q1:%d(0x%06x)\r\n",value2,value2);
    //printf("AbsPreg(REG_Q1):%d(0x%06x),PowerQ:%f\r\n",(U32)PowerQ,(U32)PowerQ,PowerQ);
    //printf("Pread:%f,Qread:%f\r\n",Preal,Qreal);

    ftmp = (PowerP*Preal+PowerQ*Qreal);
    if(ftmp== 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);
    th = (Preal*PowerQ-PowerP*Qreal)/(PowerP*Preal+PowerQ*Qreal);
    //printf("th=%f\r\n",th);
    if(th >= 0){
        gphs1 = (U32)(th*0x8000);
    }else{
        gphs1 = (U32)(0x10000+th*0x8000);
    }
    printf("gphs1=%u\r\n",gphs1);
    err = MeterAjustParaWrite(u8Chl,MAP_GPHS1,gphs1);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    float PowerP_,P_/*,PowerQ_,Q_*/;
    PowerP_ = PowerP+PowerQ*th;
    P_=PowerP_*sAdjPara[u8Chl-1].u32Kp/sRv.KGAIN[u8Chl-1];
    //PowerQ_=PowerQ-PowerP*th;
    //Q_=PowerQ_*sAdjPara.u32Kp/VALUE_K_GAIN;
    //printf("PowerP_:%f,P_:%f,PowerQ_:%f\r\n",PowerP_,P_,PowerQ_);
    //printf("PowerP_:%f,P_:%f\r\n",PowerP_,P_);

    if(P_== 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);
    float Pgain = Preal/P_ - 1;
    float gp;
    if(Pgain>=0) gp=(U32)(Pgain*0x8000);
    else gp=(U32)(0x10000+Pgain*0x8000);

    printf("Pgain:%f,gp:%f\r\n",Pgain,gp);

    err = MeterAjustParaWrite(u8Chl,MAP_GP1,gp);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    err = MeterAjustParaWrite(u8Chl,MAP_GQ1,gp);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);

    return 0;

}

// u32Value:mW
int P1OffsetAdjust(U8 u8Chl,U32 u32Value,U32 u32SmpCnt)
{
    float poffset/*,ptotal=0*/,P2;
    U32 P,value=0;
    int err;
    U32 a,b;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);

    // 先清除相关校准参数对应的寄存器
    err = MeterParaWrite(u8Chl,REG_P1OFFSETH,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    err = MeterParaWrite(u8Chl,REG_P1OFFSETL,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    OS_DELAY_MS(METER_FLUSH_DELAY); ///< 延迟350ms

    P2 = u32Value;
    P2 = P2/1000;
    /*
    ptotal = 0;
    for(int i = 0;i < 25;i++)
    {
        err = MeterParaRead(REG_P1,&value);
        METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(err);
        ptotal += AbsPreg(value);
        OS_DELAY_MS(METER_FLUSH_DELAY); //4Hz
    }
    P = (U32)(ptotal/25);
    */
    err = MeterAdjSmp(u8Chl,u32SmpCnt,8,REG_P1,&value,REG_NULL,&value);
    printf("value=%u\r\n",value);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    P = AbsPreg(value);
    printf("P=%d\r\n",P);

    poffset = (float)P2*sRv.KGAIN[u8Chl-1]/sAdjPara[u8Chl-1].u32Kp - P;
    printf("poffset=%f\r\n",poffset);

    if(poffset < 0)
    {
        poffset += 0x10000;
    }
    a = (U32)poffset;
    b = (U32)((poffset-a)*256);

    //printf("p2=%u(0x%x),p=%u(0x%x),kp=%u(0x%x)\r\n",P2,P2,P,P,sAdjPara.u32Kp,sAdjPara.u32Kp);
    printf("poffset=%f,a=%u(0x%x),b=%u(0x%x)\r\n",poffset,a,a,b,b);

    err = MeterAjustParaWrite(u8Chl,MAP_P1OFFSETH,a);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    err = MeterAjustParaWrite(u8Chl,MAP_P1OFFSETL,b);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);

    return 0;
}

// u32Value:0.01mA
int I1OffsetAdjust(U8 u8Chl,U32 u32Value,U32 u32SmpCnt) /// 输入表台电流单位精度提高确认
{
    float i1offset/*,i1total*/,i1;
    U32 i1rmsReg,value,reg;
    int err;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    // 先清除相关校准参数对应的寄存器
    err = MeterParaWrite(u8Chl,REG_I1RMSOFFSET,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    OS_DELAY_MS(METER_FLUSH_DELAY); ///< 延迟

    i1 = u32Value;
    i1 = i1/100;

    /*
    i1total = 0;
    for(int i = 0;i < 10;i++)
    {
        err = MeterParaRead(REG_I1,&value);
        METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(err);
        i1total += value;
        OS_DELAY_MS(METER_FLUSH_DELAY); //4Hz
        //printf("REG_I1:%d(0x%x)\r\n",value,value);
    }
    i1rmsReg = (U32)(i1total/10);
    */
    err = MeterAdjSmp(u8Chl,u32SmpCnt,10,REG_I1,&value,REG_NULL,&value);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    i1rmsReg = value;

    // 功率校表法
    i1offset = (((float)i1rmsReg*i1rmsReg) - ((float)(i1/1000*i1/1000)\
    /((float)sAdjPara[u8Chl-1].u32Ki1/sRv.KGAIN[u8Chl-1]\
    *(float)sAdjPara[u8Chl-1].u32Ki1/sRv.KGAIN[u8Chl-1])))/0x8000;

    // datasheet校准方法
    // i1offset = ((float)i1rmsReg*i1rmsReg) / 0x8000;

    reg = (U32)i1offset;

    //printf("i1rmsreg=%u(0x%x),i1=%f,KrmsI1=%u(0x%x)\r\n",i1rmsReg,i1rmsReg,i1,sAdjPara.u32Ki1,sAdjPara.u32Ki1);
    printf("i1offset=%f,reg=%u(0x%x)\r\n",i1offset,reg,reg);
    err = MeterAjustParaWrite(u8Chl,MAP_I1OFFSET,reg);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);

    return 0;
}

/**
@brief 判断通道号是否有效
@param u32Chl 通道号
@retval 0无效，1有效
*/
int isDevHt7017ChlValid(U32 u32Chl)
{
    if(u32Chl < 1 || u32Chl > DEV_METER_CHL_CNT){
        return 0;
    }else{
        return 1;
    }
}

/**
@brief 副电流校准
@param u8Chl 通道号(1,2)
@param u32Value 标准源电流值0.01mA
@param u32SmpCnt 采样次数,0：默认值
@return 0：success，else：fail
*/
int KI2Adjust(U8 u8Chl,U32 u32Value,U32 u32SmpCnt)
{
    U32 reg;
    int err;
    U32 k;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    //err = MeterParaRead(REG_I1,&reg);
    err = MeterAdjSmp(u8Chl,u32SmpCnt,1,REG_I2,&reg,REG_NULL,&reg);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    if(reg == 0) METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,OPP_FAILURE);
    k = (U32)((float)u32Value* sRv.KGAIN[u8Chl-1] / ((float)reg * 100));

    err = MeterAjustParaWrite(u8Chl,MAP_KI2,k);

    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);
    return err;
}

/**
@brief 副电流有效值偏置校正
@param u8Chl 通道号(1,2)
@param u32Value 标准源电流平均值0.01mA
@param u32SmpCnt 采样次数,0：默认值
@return
0：成功
1：资源索引失败
2：写使能关闭
3：计量模块寄存器写入失败
4：NVS存储失败
*/
int I2OffsetAdjust(U8 u8Chl,U32 u32Value,U32 u32SmpCnt)
{
    float ioffset/*,i1total*/,i;
    U32 irmsReg,value,reg;
    int err;

    MUTEX_LOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex,MUTEX_WAIT_ALWAYS);
    // 先清除相关校准参数对应的寄存器
    err = MeterParaWrite(u8Chl,REG_I2RMSOFFSET,0);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);

    OS_DELAY_MS(METER_FLUSH_DELAY); ///< 延迟

    i = u32Value;
    i = i/100;

    /*
    i1total = 0;
    for(int i = 0;i < 10;i++)
    {
        err = MeterParaRead(REG_I1,&value);
        METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(err);
        i1total += value;
        OS_DELAY_MS(METER_FLUSH_DELAY); //4Hz
        //printf("REG_I1:%d(0x%x)\r\n",value,value);
    }
    i1rmsReg = (U32)(i1total/10);
    */
    err = MeterAdjSmp(u8Chl,u32SmpCnt,10,REG_I2,&value,REG_NULL,&value);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    irmsReg = value;

    // 功率校表法
    ioffset = (((float)irmsReg*irmsReg) - ((float)(i/1000*i/1000)\
    /((float)sAdjPara[u8Chl-1].u32Ki1/sRv.KGAIN[u8Chl-1]\
    *(float)sAdjPara[u8Chl-1].u32Ki1/sRv.KGAIN[u8Chl-1])))/0x8000;

    // datasheet校准方法
    // i1offset = ((float)i1rmsReg*i1rmsReg) / 0x8000;

    reg = (U32)ioffset;

    //printf("i1rmsreg=%u(0x%x),i1=%f,KrmsI1=%u(0x%x)\r\n",i1rmsReg,i1rmsReg,i1,sAdjPara.u32Ki1,sAdjPara.u32Ki1);
    //printf("i1offset=%f,reg=%u(0x%x)\r\n",i1offset,reg,reg);
    err = MeterAjustParaWrite(u8Chl,MAP_I2OFFSET,reg);
    METER_ERR_CHECK_WITH_RETURN_ADJ_MUTEX_UNLOCK(u8Chl,err);
    MUTEX_UNLOCK(sDevHt7017Rts[u8Chl-1].g_MeterAdjustProtectMutex);

    return 0;
}

#define ERC_STATE_IDLE      0
#define ERC_STATE_CHECK     1
#define ERC_STATE_PRE_READ  2
#define ERC_STATE_RESET     3
#define ERC_STATE_READ      4
#define ERC_STATE_WAIT      5

#define ERC_T0_CHECK 30*1000
#define ERC_T_DELAY  650

/*返回值表示增量值*/
uint16_t ElecCalcIncEnergy(U8 u8Chl,uint16_t energy)
{
	//uint16_t u16EnergyReg = 0;
	uint16_t u16IncEnergy = 0;

    /*
	//MUTEX_LOCK(g_stElecMutex, MUTEX_WAIT_ALWAYS);
	u16EnergyReg = energy;
	if (u16EnergyReg >= g_u16LastEnergyReg[u8Chl-1]) {
		u16IncEnergy = u16EnergyReg - g_u16LastEnergyReg[u8Chl-1];
	} else {
		u16IncEnergy = MAX_ENERGY_REG_VALUE - g_u16LastEnergyReg[u8Chl-1] + u16EnergyReg;
	}

    g_u16LastEnergyReg[u8Chl-1] = u16EnergyReg;

    if (u16IncEnergy > MAX_ENERGY_REG_VALUE_PER_30S) {
        u16IncEnergy = 0;
    }

	//MUTEX_UNLOCK(g_stElecMutex);*/

	return u16IncEnergy;
}


U32 ErcRegRepair(U8 u8Chl)
{
    U32 err;
    err =  MeterRegRepairAll(u8Chl);

    return err;
}

int ErcMeterCheck(U8 u8Chl,meter_info_t* const pm)
{
    float pf;
    static U32 su32Ec[DEV_METER_CHL_CNT] = {0};
    int ret=0;
    //U8 u8Sku = 0;
    U32 u32Chl;

    if(pm == 0) return 1;

    //if(DrvSkuGet(&u8Sku) != 0)
    //{
    //    u8Sku = 3; // 默认按照两路的参数来检查
    //}
    //if(u8Sku == 0 || u8Sku == 1) {u32Chl = 1;}
    //else {u32Chl = 2;}
    u32Chl = 1;

    // 电能(100W一分钟走20下，100W 30S 走10下，400W 30S走40下)
    if(pm->u16Energy > su32Ec[u8Chl-1])
    {
        if(pm->u16Energy - su32Ec[u8Chl-1] > u32Chl*11)
        {
            ret = 6;
        }
    }
    su32Ec[u8Chl-1] = pm->u16Energy;
    if(ret != 0) return ret;

    // 电压,0.1V
    if( (pm->u32Voltage < 1760 ) || (pm->u32Voltage > 2640 )) return 8;

    // 电流,mA
    if(pm->u32Current > u32Chl*1600) return 3; // 改成固定判断范围1.6A，张俊，2019年8月15日

    // 漏电电流，mA
#ifdef CONFIG_DRV_METER_LC
    if(pm->u32LkCurrent > 30) return 7;
#endif
    // 功率,0.1mW
    if(pm->u32Power > u32Chl*4000000 ) return 4;

    // pf值,1/1000
    if((pm->u32Current > 5)&&(pm->u32Power > 5000 )&&(pm->u32Voltage!=0))
    {
        pf = pm->u32Voltage;
        pf = pf * pm->u32Current;
        pf = pm->u32Power/pf;
        if(pf > 1.1) return 5;
    }

    return ret;
}

int ErcMeterSave(U8 u8Chl,meter_info_t* pm)
{
	/*uint16_t u16IncEnergy = 0;
	NORMAL_ELECTRIC_INFO_ST ElecInfo;

    if(pm == 0) return 1;

	ElecInfo.current = pm->u32Current;//(mA)
	ElecInfo.voltage = pm->u32Voltage; //(V)
	ElecInfo.power = pm->u32Power;
	ElecInfo.factor= pm->u32PowerFactor;//单位千分之一
	u16IncEnergy = ElecCalcIncEnergy(u8Chl,pm->u16Energy);
	ElecInfo.consumption = u16IncEnergy;
	ElecInfo.delta = u16IncEnergy;
	ElecInfo.lc = pm->u32LkCurrent;
	return ElecSetElectricInfo(u8Chl,&ElecInfo);*/
    return 0;
}

/**
    计量模块寄存器巡查纠正
*/
void ErcRegCheckLoop(void)
{
    static U32 u32ERCTick[DEV_METER_CHL_CNT]={0};
    static U32 u32ERCState[DEV_METER_CHL_CNT]={0};
    static U32 u32FirstRead[DEV_METER_CHL_CNT]={0};
    static U32 u32ERCWaitTick[DEV_METER_CHL_CNT]={0};
    U32 tick,interval;
    int ret;
	meter_info_t meter_info;
	U8 err;
	U32 ecnt;
	U8 u8Chl = 0;

    for(int i = 0;i < DEV_METER_CHL_CNT;i++)
    {
        u8Chl = i + 1;
        switch(u32ERCState[i])
        {
            case ERC_STATE_IDLE:
            tick = OS_GET_TICK();
            interval = tick - u32ERCTick[i];
            if(u32FirstRead[i]==0 || interval >= ERC_T0_CHECK)
            {
                u32FirstRead[i] = 1;
                u32ERCTick[i] = tick;
                u32ERCState[i] = ERC_STATE_CHECK;
            }
            break;

            case ERC_STATE_CHECK:
            ecnt = ErcRegRepair(u8Chl);
            DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_INFO, "ErcRegRepair %d,tick=%u,ecnt=%u\r\n",u8Chl,OS_GET_TICK(),ecnt);
            if(ecnt >= 2) // 只要出现2个寄存器问题就复位
            {
                u32ERCState[i] = ERC_STATE_RESET;
            }
            else if(ecnt == 1)
            {
                u32ERCState[i] = ERC_STATE_WAIT;
                u32ERCWaitTick[i] = OS_GET_TICK();
            }
            else
            {
                u32ERCState[i] = ERC_STATE_PRE_READ;
            }
            break;

            case ERC_STATE_WAIT:
            if(OS_TICK_DIFF(u32ERCWaitTick[i], OS_GET_TICK())>=ERC_T_DELAY)
            {
                u32ERCState[i] = ERC_STATE_PRE_READ;
            }
            break;

            case ERC_STATE_PRE_READ:
            // Read
            DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_INFO, "ERC_STATE_PREREAD(%d),tick=%d\r\n",u8Chl,OS_GET_TICK());
            ret = MeterInfoGet(u8Chl,&meter_info);
    		if(0 == ret)
    		{
                // Check var
                ret = ErcMeterCheck(u8Chl,&meter_info);
                if(ret!= 0)
                {
                    DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_ERROR, "ErcMeterCheck fail(%d),err=%d\r\n",u8Chl,ret);
                    u32ERCState[i] = ERC_STATE_RESET;
                }
                else
                {
                    ErcMeterSave(u8Chl,&meter_info);
                    u32ERCState[i] = ERC_STATE_IDLE;
                    m_ucMeterInit[i] = 1;
                }
    		}else{
    		    // Read fail
    		    DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_ERROR, "MeterRead fail(%d),err=%d\r\n",u8Chl,ret);
                u32ERCState[i] = ERC_STATE_IDLE;
    		}
            break;

            case ERC_STATE_RESET:
            DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_INFO, "ERC_STATE_RESET(%d),tick=%d\r\n",u8Chl,OS_GET_TICK());
            err = MeterReinit();
            if(err != 0) DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_ERROR, "MeterReinit fail(%d),err=%u\r\n",u8Chl,err);
            u32ERCState[i] = ERC_STATE_READ;
            break;

            case ERC_STATE_READ:
            DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_INFO, "ERC_STATE_READ(%d),tick=%d\r\n",u8Chl,OS_GET_TICK());
            u32ERCState[i] = ERC_STATE_IDLE;
            ret = MeterInfoGet(u8Chl,&meter_info);
            if(ret == 0){
                ErcMeterSave(u8Chl,&meter_info);
                m_ucMeterInit[i] = 1;
            }else{
                DEBUG_LOG(DEBUG_MODULE_ELEC, DLL_ERROR, "MeterRead fail(%d),err=%d\r\n",u8Chl,ret);
            }
            break;

            default:
            u32ERCState[i] = ERC_STATE_IDLE;
            break;
        }
    }
}




